package cn.chiship.sdk.third.service;

import cn.chiship.sdk.cache.service.RedisService;
import cn.chiship.sdk.core.base.BaseResult;
import cn.chiship.sdk.core.exception.ExceptionUtil;
import cn.chiship.sdk.core.exception.custom.BusinessException;
import cn.chiship.sdk.core.util.ObjectUtil;
import cn.chiship.sdk.core.util.PrintUtil;
import cn.chiship.sdk.core.util.StringUtil;
import cn.chiship.sdk.core.util.http.HttpUtil;
import cn.chiship.sdk.third.core.common.ThirdConstants;
import cn.chiship.sdk.third.core.model.YsConfigModel;
import cn.chiship.sdk.third.properties.ChishipYsProperties;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;

/**
 * 萤石云相关服务 URL:https://open.ys7.com/help
 *
 * @author lijian
 */
@Component
public class YsService {

    /**
     * 萤石 Server服务主机
     */
    public static final String API_YS_SERVER_HOST = "https://open.ys7.com/api/";

    private static final Logger LOGGER = LoggerFactory.getLogger(YsService.class);

    private static final String ACCESS_TOKEN = "accessToken";

    private YsConfigModel ysConfigModel;

    private String accessToken = null;

    @Resource
    ChishipYsProperties chishipYsProperties;

    @Resource
    RedisService redisService;

    public YsService config() {
        this.ysConfigModel = new YsConfigModel(chishipYsProperties.getAppKey(), chishipYsProperties.getAppSecret());
        return this;
    }

    public YsService config(YsConfigModel ysConfigModel) {
        if (ObjectUtils.isEmpty(ysConfigModel)) {
            LOGGER.info("萤石实例配置为空，将自动加载默认配置信息");
            return config();
        }
        this.ysConfigModel = ysConfigModel;
        return this;
    }

    public YsService token() {
        BaseResult baseResult = getToken();
        if (!baseResult.isSuccess()) {
            throw new BusinessException(JSON.toJSONString(baseResult.getData()));
        }
        this.accessToken = baseResult.getData().toString();
        return this;
    }

    /**
     * 获取接口调用凭据 URL:https://open.ys7.com/help/81
     *
     * @return BaseResult
     */
    private BaseResult getToken() {

        try {
            String url = API_YS_SERVER_HOST + "lapp/token/get";

            String key = ThirdConstants.REDIS_YS_ACCESS_TOKEN + ":" + this.ysConfigModel.getAppKey();
            String token = StringUtil.getString(redisService.get(key), null);
            if (!StringUtil.isNullOrEmpty(token)) {
                return BaseResult.ok(token);
            }
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("appKey", this.ysConfigModel.getAppKey());
            bodies.put("appSecret", this.ysConfigModel.getAppSecret());
            PrintUtil.console(bodies);
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            baseResult = analysisHttpResponse(baseResult);
            if (!baseResult.isSuccess()) {
                return baseResult;
            }
            JSONObject dataJson = (JSONObject) baseResult.getData();

            token = dataJson.getString(ACCESS_TOKEN);
            long expireTime = Long.parseLong(dataJson.getString("expireTime"));
            long expiresIn = expireTime - System.currentTimeMillis();
            baseResult.setData(token);
            // 提前5分钟过期
            redisService.set(key, token, expiresIn - 5 * 60);
            return baseResult;
        } catch (Exception e) {
            return ExceptionUtil.formatException(e);
        }
    }

    /**
     * 设备列表 URL:https://open.ys7.com/help/673
     *
     * @param pageStart 分页起始页，从1开始
     * @param pageSize  分页大小，默认为10，最大为50
     * @return
     */
    public BaseResult deviceList(int pageStart, int pageSize) {
        try {
            String url = API_YS_SERVER_HOST + "lapp/device/list";
            pageStart -= 1;
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("pageStart", StringUtil.getString(pageStart));
            bodies.put("pageSize", StringUtil.getString(pageSize));
            bodies.put("accessToken", this.accessToken);
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 获得单个设备信息 URL:https://open.ys7.com/help/672
     *
     * @param deviceSerial 设备序列号 序列号
     * @return
     */
    public BaseResult getDeviceInfo(String deviceSerial) {

        try {
            String url = API_YS_SERVER_HOST + "lapp/device/info";
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("deviceSerial", deviceSerial);
            bodies.put("accessToken", this.accessToken);
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 未安装设备基础信息查询 添加新设备或查询新设备基础信息 URL:https://open.ys7.com/help/660
     *
     * @param deviceSerial 设备序列号 序列号
     * @return
     */
    public BaseResult getDeviceBaseInfo(String deviceSerial) {
        try {
            String url = API_YS_SERVER_HOST + "v3/device/searchDeviceInfo";
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("deviceSerial", deviceSerial);
            bodies.put("accessToken", this.accessToken);
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 添加设备 URL:https://open.ys7.com/help/661
     *
     * @param deviceSerial 设备序列号 序列号
     * @param validateCode
     * @return
     */
    public BaseResult deviceAdd(String deviceSerial, String validateCode) {
        try {
            String url = API_YS_SERVER_HOST + "lapp/device/add";
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("deviceSerial", deviceSerial);
            bodies.put("validateCode", validateCode);
            bodies.put("accessToken", this.accessToken);
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 删除设备 URL:https://open.ys7.com/help/662
     *
     * @param deviceSerial 设备序列号,存在英文字母的设备序列号，字母需为大写
     * @return
     */
    public BaseResult deviceDelete(String deviceSerial) {

        try {
            String url = API_YS_SERVER_HOST + "lapp/device/delete";
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("deviceSerial", deviceSerial);
            bodies.put("accessToken", this.accessToken);
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 获取视频通道列表 URL:https://open.ys7.com/help/674
     *
     * @param pageStart 分页起始页，从1开始
     * @param pageSize  分页大小，默认为10，最大为50
     * @return
     */
    public BaseResult cameraList(int pageStart, int pageSize) {
        try {
            String url = API_YS_SERVER_HOST + "lapp/camera/list";
            pageStart -= 1;
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("pageStart", StringUtil.getString(pageStart));
            bodies.put("pageSize", StringUtil.getString(pageSize));
            bodies.put("accessToken", this.accessToken);
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 获取指定设备的通道信息 URL:https://open.ys7.com/help/1478
     *
     * @param deviceSerial 设备序列号 序列号
     * @return
     */
    public BaseResult getDeviceCamera(String deviceSerial) {

        try {
            String url = API_YS_SERVER_HOST + "lapp/device/camera/list";
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("deviceSerial", deviceSerial);
            bodies.put("accessToken", this.accessToken);
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 获取设备状态信息 URL:https://open.ys7.com/help/675
     *
     * @param deviceSerial 设备序列号 序列号
     * @return
     */
    public BaseResult getDeviceStatus(String deviceSerial) {
        return getDeviceStatus(deviceSerial, null);
    }

    /**
     * 获取设备状态信息 URL:https://open.ys7.com/help/675
     *
     * @param deviceSerial 设备序列号 序列号
     * @param channel      通道
     * @return
     */
    public BaseResult getDeviceStatus(String deviceSerial, Integer channel) {

        try {
            String url = API_YS_SERVER_HOST + "lapp/device/status/get";
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("deviceSerial", deviceSerial);
            if (!StringUtil.isNull(channel)) {
                bodies.put("channel", channel);
            }
            bodies.put("accessToken", this.accessToken);
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 获取NVR通道状态信息 URL:https://open.ys7.com/help/676
     *
     * @param deviceSerial 设备序列号 序列号
     * @return
     */
    public BaseResult getDeviceChannelStatus(String deviceSerial) {

        try {
            String url = API_YS_SERVER_HOST + "v3/open/device/metadata/channel/status";
            Map<String, String> headers = new HashMap<>(7);
            headers.put("deviceSerial", deviceSerial);
            headers.put("accessToken", this.accessToken);
            BaseResult baseResult = HttpUtil.getInstance().headers(headers).doGet(url);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 修改设备名称 URL:https://open.ys7.com/help/667
     *
     * @param deviceSerial 设备序列号
     * @param deviceName
     * @return
     */
    public BaseResult deviceNameUpdate(String deviceSerial, String deviceName) {
        try {
            if (StringUtil.isNullOrEmpty(deviceName)) {
                return BaseResult.error("设备名称不能为空");
            }
            if (deviceName.length() > 50) {
                return BaseResult.error("设备名称不能超过50个字符");
            }
            String url = API_YS_SERVER_HOST + "lapp/device/name/update";
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("deviceSerial", deviceSerial);
            bodies.put("deviceName", deviceName);
            bodies.put("accessToken", this.accessToken);
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 修改设备通道名称 URL:https://open.ys7.com/help/668
     *
     * @param deviceSerial 设备序列号
     * @param cameraName
     * @return
     */
    public BaseResult deviceCameraNameUpdate(String deviceSerial, String cameraName) {
        return deviceCameraNameUpdate(deviceSerial, cameraName, 1);
    }

    /**
     * 修改设备通道名称 URL:https://open.ys7.com/help/668
     *
     * @param deviceSerial 设备序列号
     * @param cameraName
     * @param channelNo
     * @return
     */
    public BaseResult deviceCameraNameUpdate(String deviceSerial, String cameraName, Integer channelNo) {
        try {
            if (StringUtil.isNullOrEmpty(cameraName)) {
                return BaseResult.error("通道名称不能为空");
            }
            if (cameraName.length() > 50) {
                return BaseResult.error("通道名称不能超过50个字符");
            }
            String url = API_YS_SERVER_HOST + "lapp/camera/name/update";
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("deviceSerial", deviceSerial);
            bodies.put("name", cameraName);
            bodies.put("channelNo", channelNo);
            bodies.put("accessToken", this.accessToken);
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 获得直播地址 URL:https://open.ys7.com/help/1414
     *
     * @param deviceSerial 设备序列号
     * @return
     */
    public BaseResult getLiveAddress(String deviceSerial) {
        try {
            String url = API_YS_SERVER_HOST + "lapp/v2/live/address/get";
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("deviceSerial", deviceSerial);
            bodies.put("accessToken", this.accessToken);
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 获取能力集 URL:https://open.ys7.com/help/678
     *
     * @param deviceSerial 设备序列号
     * @return
     */
    public BaseResult deviceCapacity(String deviceSerial) {
        try {
            String url = API_YS_SERVER_HOST + "lapp/device/capacity";
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("deviceSerial", deviceSerial);
            bodies.put("accessToken", this.accessToken);
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            baseResult = analysisHttpResponse(baseResult);
            baseResult = getCapacityDesc(baseResult);
            return baseResult;
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 设备视频加密&解密 URL:https://open.ys7.com/help/697 https://open.ys7.com/help/698
     *
     * @param deviceSerial 设备序列号
     * @param encrypt
     * @return
     */
    public BaseResult deviceEncrypt(String deviceSerial, Boolean encrypt) {
        try {
            String url = API_YS_SERVER_HOST
                    + (Boolean.TRUE.equals(encrypt) ? "lapp/device/encrypt/on" : "lapp/device/encrypt/off");
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("accessToken", this.accessToken);
            bodies.put("deviceSerial", deviceSerial);
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 设备智能检测开关获取 URL:https://open.ys7.com/help/726
     *
     * @param deviceSerial 设备序列号
     * @return
     */
    public BaseResult detectionSwitch(String deviceSerial) {

        try {
            String url = API_YS_SERVER_HOST + "lapp/device/intelligence/detection/switch/status";

            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("accessToken", this.accessToken);
            bodies.put("deviceSerial", deviceSerial);
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 设备智能检测开关设置 该该接口用于获取设备智能检测开关状态(该接口仅用于智能设备,如C5SI,如需使用该接口,请联系萤石开放平台确认设备功能)
     * URL:https://open.ys7.com/help/727
     *
     * @param deviceSerial 设备序列号
     * @param open
     * @return
     */
    public BaseResult detectionSwitchSet(String deviceSerial, Boolean open) {
        try {
            String url = API_YS_SERVER_HOST + "lapp/device/intelligence/detection/switch/set";
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("accessToken", this.accessToken);
            bodies.put("deviceSerial", deviceSerial);
            bodies.put("enable", open ? "1" : "0");
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 设备灵敏度 URL:https://open.ys7.com/help/714
     *
     * @param deviceSerial 设备序列号
     * @return
     */
    public BaseResult algorithmGet(String deviceSerial) {

        try {
            String url = API_YS_SERVER_HOST + "lapp/device/algorithm/config/get";
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("accessToken", this.accessToken);
            bodies.put("deviceSerial", deviceSerial);
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 设备灵敏度设置
     *
     * @param deviceSerial 设备序列号
     * @param algorithm
     * @return
     */
    public BaseResult algorithmSet(String deviceSerial, int algorithm) {
        try {
            String url = API_YS_SERVER_HOST + "lapp/device/algorithm/config/set";
            if (algorithm > 6 || algorithm < 1) {
                return BaseResult.error("灵敏度取值范围为1~6");
            }
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("accessToken", this.accessToken);
            bodies.put("deviceSerial", deviceSerial);
            bodies.put("value", String.valueOf(algorithm));
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 获取所有告警列表 URL:https://open.ys7.com/help/986
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return
     */
    public BaseResult alarmList(Long startTime, Long endTime) {
        try {
            String url = API_YS_SERVER_HOST + "lapp/alarm/list";
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("accessToken", this.accessToken);
            if (!StringUtil.isNull(startTime)) {
                bodies.put("startTime", StringUtil.getString(startTime));
            }
            if (!StringUtil.isNull(endTime)) {
                bodies.put("endTime", StringUtil.getString(endTime));
            }
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }

    }

    /**
     * 获得某个设备告警列表 URL:https://open.ys7.com/help/987
     *
     * @param pageSize     条数
     * @param pageStart    页码
     * @param deviceSerial 设备序列号
     * @return
     */
    public BaseResult alarmDeviceList(int pageStart, int pageSize, String deviceSerial) {
        return alarmDeviceList(pageStart, pageSize, deviceSerial, null, null);
    }

    /**
     * 获得某个设备告警列表 URL:https://open.ys7.com/help/987
     *
     * @param pageSize     条数
     * @param pageStart    页码
     * @param deviceSerial 设备序列号
     * @param startTime    开始时间
     * @param endTime      结束时间
     * @return
     */
    public BaseResult alarmDeviceList(int pageStart, int pageSize, String deviceSerial, Long startTime, Long endTime) {

        try {
            String url = API_YS_SERVER_HOST + "lapp/alarm/device/list";
            pageStart -= 1;
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("accessToken", this.accessToken);
            bodies.put("deviceSerial", deviceSerial);
            bodies.put("pageStart", StringUtil.getString(pageStart));
            bodies.put("pageSize", StringUtil.getString(pageSize));
            if (!StringUtil.isNull(startTime)) {
                bodies.put("startTime", StringUtil.getString(startTime));
            }
            if (!StringUtil.isNull(endTime)) {
                bodies.put("endTime", StringUtil.getString(endTime));
            }
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 开启设备消息订阅 URL:https://open.ys7.com/help/567
     *
     * @param deviceSerial 设备序列号
     * @return
     */
    public BaseResult notificationSubscribe(String deviceSerial) {

        try {
            String url = API_YS_SERVER_HOST + "open/cloud/ISAPI/Event/notification/subscribeEvent";
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("accessToken", this.accessToken);
            bodies.put("deviceSerial", deviceSerial);
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 获取设备版本信息 URL:https://open.ys7.com/help/734
     *
     * @param deviceSerial 设备序列号
     * @return
     */
    public BaseResult deviceVersionInfo(String deviceSerial) {
        try {
            String url = API_YS_SERVER_HOST + "lapp/device/version/info";
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("accessToken", this.accessToken);
            bodies.put("deviceSerial", deviceSerial);
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 设备升级固件 URL:https://open.ys7.com/help/735
     *
     * @param deviceSerial 设备序列号
     * @return
     */
    public BaseResult deviceUpgrade(String deviceSerial) {
        try {
            String url = API_YS_SERVER_HOST + "lapp/device/upgrade";
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("accessToken", this.accessToken);
            bodies.put("deviceSerial", deviceSerial);
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 设备升级固件状态 URL:https://open.ys7.com/help/736
     *
     * @param deviceSerial 设备序列号
     * @return
     */
    public BaseResult deviceUpgradeStatus(String deviceSerial) {
        try {
            String url = API_YS_SERVER_HOST + "lapp/device/upgrade/status";
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("accessToken", this.accessToken);
            bodies.put("deviceSerial", deviceSerial);
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 获取设备模块升级信息 URL:https://open.ys7.com/help/2856
     *
     * @param deviceSerial 设备序列号
     * @return
     */
    public BaseResult deviceModulesInfo(String deviceSerial) {
        try {
            String url = API_YS_SERVER_HOST + "/service/device/upgrade/modules";
            Map<String, String> headers = new HashMap<>(7);
            headers.put("accessToken", this.accessToken);
            Map<String, Object> queries = new HashMap<>(7);
            queries.put("deviceSerial", deviceSerial);
            BaseResult baseResult = HttpUtil.getInstance().headers(headers).doGet(url, queries);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 触发设备模块升级 URL:https://open.ys7.com/help/2858
     *
     * @param deviceSerial 设备序列号
     * @param modules
     * @return
     */
    public BaseResult deviceModuleUpgrade(String deviceSerial, List<String> modules) {
        if (ObjectUtil.isEmpty(modules)) {
            return BaseResult.error("升级模块不能为空！");
        }
        if (modules.isEmpty()) {
            return BaseResult.error("升级模块不能为空！");
        }
        try {
            String url = API_YS_SERVER_HOST + "v3/device/upgrade/modules";
            Map<String, String> headers = new HashMap<>(7);
            headers.put("accessToken", this.accessToken);
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("deviceSerial", deviceSerial);
            bodies.put("modules", StringUtil.join(modules, ","));
            BaseResult baseResult = HttpUtil.getInstance().headers(headers).doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 获取设备模块升级状态 URL:https://open.ys7.com/help/2857
     *
     * @param deviceSerial 设备序列号
     * @return
     */
    public BaseResult deviceModuleUpgradeStatus(String deviceSerial, String module) {
        try {
            String url = API_YS_SERVER_HOST + "service/device/upgrade/modules/status";
            Map<String, String> headers = new HashMap<>(7);
            headers.put("accessToken", this.accessToken);
            Map<String, Object> queries = new HashMap<>(7);
            queries.put("deviceSerial", deviceSerial);
            queries.put("module", module);
            BaseResult baseResult = HttpUtil.getInstance().headers(headers).doGet(url, queries);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    /**
     * 语音文件查询 URL:https://open.ys7.com/help/1247
     *
     * @return
     */
    public BaseResult voiceQuery() {
        try {
            String url = API_YS_SERVER_HOST + "lapp/voice/query";
            Map<String, Object> bodies = new HashMap<>(7);
            bodies.put("accessToken", this.accessToken);
            BaseResult baseResult = HttpUtil.getInstance().doPostForm(url, bodies);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return BaseResult.error(ExceptionUtil.formatException(e));
        }
    }

    public String getAccessToken() {
        if (StringUtil.isNullOrEmpty(accessToken)) {
            throw new BusinessException("token为空！请链式调用如下方法：config().token()获得Token");
        }
        return accessToken;
    }

    /**
     * 包装能力集
     *
     * @return
     */
    public static BaseResult getCapacityDesc(BaseResult baseResult) {
        if (!baseResult.isSuccess()) {
            return baseResult;
        }
        Map<String, String> map = new HashMap<>(2);
        map.put("support_defence", "是否支持布撤防,活动检测开关");
        map.put("support_talk", "是否支持对讲: 0-不支持, 1-全双工, 3-半双工");
        map.put("support_defenceplan", "是否支持布撤防计划 0-不支持， 1-支持,2-支持新的设备计划协议");
        map.put("support_disk", "是否支持存储格式化 0-不支持, 1-支持");
        map.put("support_privacy", "是否支持隐私保护 0-不支持, 1-支持");
        map.put("support_message", "是否支持留言 0-不支持, 1-支持");
        map.put("support_alarm_voice", "是否支持告警声音配置 0-不支持, 1-支持");
        map.put("support_auto_offline", "是否支持设备自动上下线 0-不支持, 1-支持");
        map.put("supprot_encrypt", "是否支持视频图像加密 0-不支持, 1-支持");
        map.put("support_upgrade", "是否支持设备升级 0-不支持, 1-支持");
        map.put("support_cloud", "该设备型号是否支持云存储 0-不支持, 1-支持");
        map.put("support_cloud_version",
                "该设备版本是否支持云存储 0-不支持, 1-支持。需要和support_cloud组合使用:support_cloud = 1 , support_cloud_version = 1 才支持云存储  support_cloud =1 ,support_cloud_version = 0,该型号的设备支持云存储,但是当前固件版本不支持云存储  support_cloud = 0 该型号的设备不支持云存储");
        map.put("support_wifi", "是否支持WI-FI:0-不支持, 1-支持netsdk配置WI-FI,2-支持带userId的新WI-FI配置方式,3-支持一键配置WI-FI");
        map.put("support_capture", "是否支持封面抓图 0-不支持, 1-支持");
        map.put("support_modify_pwd", "是否支持修改设备加密密码 0-不支持, 1-支持");
        map.put("support_resolution", "视频播放比例 16-9表示16:9分辨率,默认16-9");
        map.put("support_multi_screen", "是否支持多画面播放 0-不支持, 1-支持(客户端使用,与设备无关)");
        map.put("support_upload_cloud_file", "是否支持手机拍照上传到云存储 0-不支持, 1-支持");
        map.put("support_add_del_detector", "是否支持app远程添加删除外设(探测器) 0-不支持, 1-支持");
        map.put("support_ipc_link", "是否支持IPC与A1联动关系设置 0-不支持, 1-支持");
        map.put("support_modify_detectorname", "是否支持修改外设(探测器)名称 0-不支持, 1-支持");
        map.put("support_safe_mode_plan", "是否支持定时切换安全功能模式 0-不支持, 1-支持");
        map.put("support_weixin", "是否支持微信互联:0-不支持, 1-支持");
        map.put("support_ssl", "是否支持声源定位:0-不支持, 1-支持");
        map.put("support_related_device", "是否支持关联设备 0-无关联设备, 1-关联监控点或N1, 2-关联探测器或A1, 3-关联监控点探测器或R1, 4关联多通道设备");
        map.put("support_related_storage", "NVR/R1是否支持关联IPC存储: 0-不支持, 1-支持");
        map.put("support_remote_auth_randcode", "是否支持设备远程授权获取密码, 0-不支持, 1-支持");
        map.put("support_sdk_transport", "是否支持设备跨公网配置的能力级：0-不支持, 1-支持");
        map.put("ptz_top_bottom", "是否支持云台上下转动 0-不支持, 1-支持");
        map.put("ptz_left_right", "是否支持云台左右转动 0-不支持, 1-支持");
        map.put("ptz_45", "是否支持云台45度方向转动 0-不支持, 1-支持");
        map.put("ptz_zoom", "是否支持云台缩放控制 0-不支持, 1-支持");
        map.put("support_ptz", "是否支持云台控制 0-不支持, 1-支持");
        map.put("ptz_preset", "是否支持云台预置点 0-不支持, 1-支持");
        map.put("ptz_common_cruise", "是否支持普通巡航 0-不支持, 1-支持");
        map.put("ptz_figure_cruise", "是否支持花样巡航 0-不支持, 1-支持");
        map.put("ptz_center_mirror", "是否支持中心镜像 0-不支持, 1-支持");
        map.put("ptz_left_right_mirror", "是否支持左右镜像 0-不支持, 1-支持");
        map.put("ptz_top_bottom_mirror", "是否支持上下镜像 0-不支持, 1-支持");

        map.put("ptz_close_scene", "是否支持关闭镜头 0-不支持, 1-支持");
        map.put("support_wifi_2.4G", "是否支持2.4G无线频段 0-不支持, 1-支持");
        map.put("support_wifi_5G", "是否支持5G无线频段 0-不支持, 1-支持");
        map.put("support_wifi_portal", "是否支持营销wifi，只有support_wifi_2.4G=1的时候才生效：1-支持但不能设置营销页（X1），2-支持且可以设置营销页，0-不支持");
        map.put("support_unbind", "是否支持用户解绑设备 0-不支持, 1-支持reset键解绑，2-支持界面点击确定按钮解绑");
        map.put("support_auto_adjust", "是否支持自适应码流 0-不支持, 1-支持");
        map.put("support_timezone", "是否支持时区配置 0-不支持, 1-支持");
        map.put("support_language", "支持的语言类型：ENGLISH,SIMPCN,....");
        map.put("support_close_infrared_light", "是否支持红外开关 0-不支持, 1-支持");
        map.put("support_modify_chan_name", "是否支持通道名称配置到设备（IPC/NVR) 0-不支持, 1-支持");
        map.put("support_ptz_model", "0-支持直连+转发云台控制， 1-支持直连云台控制，2-支持转发云台控制");
        map.put("support_talk_type", "0-采用上面的麦克风, 1-对讲采用下面的麦克风");
        map.put("support_chan_type", "通道类型，1-数字通道，2-模拟通道");
        map.put("support_flow_statistics", "是否支持客流统计 0-不支持, 1-支持");
        map.put("support_more", "是否支持设备设置功能 0-不支持, 1-支持");
        map.put("support_remote_quiet", "A1是否支持远程消警（静音）功能 0-不支持, 1-支持");
        map.put("support_customize_rate", "是否支持自定义码率 0-不支持, 1-支持");
        map.put("support_rectify_image", "是否支持畸形矫正 0-不支持, 1-支持");
        map.put("support_bluetooth", "是否支持蓝牙 0-不支持, 1-支持");
        map.put("support_p2p_mode", "默认0，表示老的p2p协议；配置为1，表示该版本支持新的p2p协议");
        map.put("support_microscope", "是否支持显微镜功能 0-不支持, 1-支持");
        map.put("support_sensibility_adjust", "是否支持移动侦测灵敏度调节 0-不支持, 1-支持");
        map.put("support_sleep", "是否支持睡眠功能 0-不支持, 1-支持");
        map.put("support_audio_onoff", "是否支持声音开关设置 0-不支持, 1-支持");
        map.put("support_protection_mode", "0：无防护模式，可能有活动检测（根据support_denfence(序号1)判断）");
        map.put("support_rate_limit", "是否支持高清码率限制 0-不支持码率限制, 1-支持高清码率限制");
        map.put("support_userId", "是否支持通过UserID关联设备 0-不支持, 1-支持");
        map.put("support_music", "是否支持儿歌播放功能 0-不支持, 1-支持");
        map.put("support_replay_speed", "是否支持调节回放播放速度功能 0-不支持, 1-支持");
        map.put("support_reverse_direct", "是否支持反向直连功能 0-不支持, 1-支持");
        map.put("support_channel_offline_notify", "是否支持通道下线通知,支持后通道下线会触发ideoloss的告警 0-不支持, 1-支持");
        map.put("support_fullscreen_ptz", "是否支持全景云台功能0-不支持, 1-支持");
        map.put("support_preset_alarm", "是否支持预置点告警联动 0-不支持, 1-支持");
        map.put("support_intelligent_track", "是否支持智能跟踪 0-不支持, 1-支持");
        map.put("support_key_focus", "是否支持一键聚焦 0-不支持, 1-支持");
        map.put("support_volumn_set", "是否支持音量调节 0-不支持, 1-支持");
        map.put("support_temperature_alarm", "是否支持温湿度告警  0-不支持, 1-支持( F2、C1S等带温湿度传感器的摄像机支持)");
        map.put("support_mcvolumn_set", "是否支持麦克风音量调节 0-不支持, 1-支持");
        map.put("support_unlock", "是否支持支持开锁 0-不支持, 1-支持");
        map.put("support_noencript_via_antproxy", "是否支持支持走代理时可以自动加密“没有开启视频加密”的流 0-不支持, 1-支持");
        map.put("support_device_offline_notify", "是否支持设备下线通知 0-不支持, 1-支持");
        map.put("support_fullscreen_ptz_12", "是否支持全景云台功能 0-不支持, 1-支持");
        map.put("support_speech_recognition", "是否支持语音识别 0-不支持, 1-支持");
        map.put("support_message_cover", "是否支持留言封面 0-不支持, 1-支持");
        map.put("support_nat_pass", "是否支持NAT组合为3-4的NAT穿透（P2PV2.1） 0-不支持, 1-支持");
        map.put("support_nvr_whitelist", "NVR是否支持白名单成员管理 0-不支持, 1-支持");
        map.put("support_voice_alarmclock", "是否支持语音闹钟功能 0-不支持, 1-支持");
        map.put("support_new_talk", "是否支持新对讲服务 0-不支持, 1-支持");
        map.put("support_fullday_record", "是否支持全天录像配置开关 0-不支持, 1-支持");
        map.put("support_query_play_connections", "是否支持查询当前预览，回放链接信息 0-不支持, 1-支持");
        map.put("support_ptz_auto_reset", "是否支持云台自动复位 0-不支持, 1-支持");
        map.put("support_fisheye_mode", "是否支持鱼眼模式 0-不支持, 1-支持");
        map.put("support_custom_voice", "是否支持自定义语音 0-不支持, 1-支持(语音闹钟，告警声音使用)");
        map.put("support_new_sound_wave", "是否支持声波配置（高频版本） 0-不支持, 1-支持");
        map.put("replay_chan_nums", "X3或者N1可以关联的通道数");
        map.put("support_horizontal_panoramic", "是否支持水平全景 0-不支持, 1-支持");
        map.put("support_active_defense", "是否支持主动防御功能：0-不支持，1-主动防御按钮，2-主动防御按钮+灯光提醒开关");
        map.put("support_motion_detect_area", "是否支持移动侦测区域绘制 0-不支持, 1-支持");
        map.put("support_chan_defence", "是否支持通道布撤防 0-不支持, 1-支持");
        map.put("ptz_focus", "是否支持焦距模式 0-不支持, 1-支持");
        map.put("support_pir_detect", "是否支持红外检测能力 0-不支持, 1-支持(猫眼)");
        map.put("support_doorbell_talk", "是否支持门铃呼叫能力 0-不支持, 1-支持(猫眼)");
        map.put("support_face_detect", "是否支持人脸检测能力 0-不支持, 1-支持(猫眼)");
        map.put("support_restart_time", "设备重启时间，配置单位为秒数，默认120s");
        map.put("support_human_filter", "是是否支持人形过滤能力 0-不支持, 1-支持)(C5SI型号，设备通过智能芯片硬件来支持)");
        map.put("support_human_service", "是否支持人形检测能力 0-不支持, 1-支持 (设备+平台服务开通，实现人形检测服务能力设备通过更新软件版本可以支持)");
        map.put("support_ap_mode", "是否支持添加设备配置WiFi使用，0：不支持，1：smartconfig+声波失败后，支持AP配网，2：设备默认AP配网");
        map.put("support_continuous_cloud", "是否支持连续云存储 0-不支持, 1-支持,注:与support_cloud(序号11)完全无关");
        map.put("support_doorbell_sound", "是否支持门铃声音 0-不支持, 1-支持");
        map.put("support_associate_detector", "是否支持关联探测器 0-不支持, 1-支持");
        map.put("support_modify_username", "是否支持修改门锁用户备注名称 0-不支持, 1-支持");
        map.put("support_transfertype", "预览取流格式传输类型 0-不支持, 1-支持");
        map.put("support_vertical_panoramic", "是否支持垂直全景(与support_horizontal_panoramic(序号96)对应) 0-不支持, 1-支持");
        map.put("support_alarm_light", "是否支持安防灯 0-不支持, 1-支持");
        map.put("support_alarm_area", "是否支持安防灯 0-不支持, 1-支持");
        map.put("support_chime", "是否支持门铃扩展 0-不支持, 1-支持");
        map.put("support_video_mode", "是否支持support_video_mode 0-不支持, 1-支持");
        map.put("support_relation_camera", "是否支持W2D 关联摄像机功能 0-不支持, 1-支持");
        map.put("support_pir_setting", "是否支持PIR(红外)区域设置 0-不支持, 1-支持");
        map.put("support_battery_manage", "是否支持电量管理 0-不支持, 1-支持");

        List<JSONObject> datas = new ArrayList<>();
        JSONObject json = (JSONObject) baseResult.getData();
        Iterator it = json.keySet().iterator();
        while (it.hasNext()) {
            String key = it.next().toString();
            Object value = json.get(key);
            JSONObject data = new JSONObject();
            data.put("key", key);
            data.put("value", value);
            data.put("desc", map.containsKey(key) ? map.get(key) : null);
            datas.add(data);
        }
        baseResult.setData(datas);
        return baseResult;
    }

    private BaseResult analysisHttpResponse(BaseResult baseResult) {
        Integer successStatus = 200;
        String msgCode = "code";
        String msg = "msg";
        String dataMsg = "data";
        String pageMsg = "page";
        String resultMsg = "result";
        String metaMsg = "meta";
        if (!baseResult.isSuccess()) {
            return baseResult;
        }
        JSONObject json = JSON.parseObject(StringUtil.getString(baseResult.getData()));
        PrintUtil.console(json);

        if (!json.containsKey(msgCode)) {
            if (json.containsKey(resultMsg)) {
                return analysisHttpResponse(BaseResult.ok(json.get(resultMsg)));
            }
            if (json.containsKey(metaMsg)) {
                json.put("code", json.getJSONObject(metaMsg).getIntValue(msgCode));
                json.put("msg", json.getJSONObject(metaMsg).getString("message"));
                return analysisHttpResponse(BaseResult.ok(json));
            }
            return BaseResult.ok(json);
        } else if (successStatus.equals(json.getInteger(msgCode))) {
            if (json.containsKey(pageMsg)) {
                json.remove(msgCode);
                json.remove(msg);
                JSONObject newJson = new JSONObject();
                newJson.put("total", json.getJSONObject(pageMsg).getIntValue("total"));
                newJson.put("size", json.getJSONObject(pageMsg).getIntValue("size"));
                newJson.put("page", json.getJSONObject(pageMsg).getIntValue("page"));
                newJson.put("records", json.get(dataMsg));
                return BaseResult.ok(newJson);
            } else {
                return BaseResult.ok(json.get(dataMsg));
            }
        } else {
            return BaseResult.error("【" + json.getInteger(msgCode) + "】：" + json.getString(msg));
        }

    }

}
